package com.pocketmenu.ui;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.List;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.pocketmenu.persistence.Restaurant;
import com.pocketmenu.persistence.RestaurantDataSource;
import com.pocketmenu.ui.ProximityAlertActivity.MyLocationListener;

public class ShowPointOfInterestMapActivity extends MapActivity implements LocationListener {

	private MapController mapController;
	private MapView mapView;
	private LocationManager locationManager;
	private GeoPoint currentPoint;
	public static Location currentLocation = null;
	private PointOfInterestOverlay currPos;	
	
	//Proximity alert
	private static final long MINIMUM_DISTANCECHANGE_FOR_UPDATE = 1; // in Meters
    private static final long MINIMUM_TIME_BETWEEN_UPDATE = 1000; // in Milliseconds
    
    private static final long POINT_RADIUS = 100; // in Meters
    private static final long PROX_ALERT_EXPIRATION = -1; 

    private static final String POINT_LATITUDE_KEY = "POINT_LATITUDE_KEY";
    private static final String POINT_LONGITUDE_KEY = "POINT_LONGITUDE_KEY";
    
    private static final String PROX_ALERT_INTENT = "com.pocketmenu.ui.ProximityAlert";
    
    private static final NumberFormat nf = new DecimalFormat("##.########");       
	
    private static ProximityIntentReceiver proximityIntentReceiver = new ProximityIntentReceiver();
    
    private String restaurantAlertName;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_show_point_of_interest_map);
        
        mapView = (MapView)findViewById(R.id.mapView);
		mapView.setBuiltInZoomControls(true);		
		mapController = mapView.getController();
		mapController.setZoom(19);
		
		//Proximity alert
		getLastLocation();
		drawCurrentPositionOverlay();
		drawPointsOfInterestOverlay();
		animateToCurrentLocation();       
    }    
    
    public void getLastLocation(){
    	String provider = getBestProvider();    	
    	currentLocation = locationManager.getLastKnownLocation(provider);    	
    	if(currentLocation != null){
    		setCurrentLocation(currentLocation);
    	}    	    		
    }
    
    public void animateToCurrentLocation(){
    	if(currentPoint!=null){
    		mapController.animateTo(currentPoint);
    	}
    }
       
    public String getBestProvider(){	
		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		
		Criteria criteria = new Criteria();
    	criteria.setPowerRequirement(Criteria.NO_REQUIREMENT);
    	criteria.setAccuracy(Criteria.NO_REQUIREMENT);
    	String bestProvider = locationManager.getBestProvider(criteria, true);
    	
		locationManager.requestLocationUpdates(
                bestProvider, 
                MINIMUM_TIME_BETWEEN_UPDATE, 
                MINIMUM_DISTANCECHANGE_FOR_UPDATE,
                this
			);

		
    	return bestProvider;
    }
    
    public void setCurrentLocation(Location location){
    	int currLatitude = (int) (location.getLatitude()*1E6);
    	int currLongitude = (int) (location.getLongitude()*1E6);
    	currentPoint = new GeoPoint(currLatitude,currLongitude);     	

    	currentLocation = new Location("");
    	currentLocation.setLatitude(currentPoint.getLatitudeE6() / 1e6);
    	currentLocation.setLongitude(currentPoint.getLongitudeE6() / 1e6);
    	
//    	((TextView)findViewById(R.id.latitudeText)).setText("Latitude : " + String.valueOf((int)(location.getLatitude()*1E6)));
//    	((TextView)findViewById(R.id.longitudeText)).setText("Longitude : " +  String.valueOf((int)(location.getLongitude()*1E6)));
//    	((TextView)findViewById(R.id.accuracyText)).setText("Accuracy : " + String.valueOf(location.getAccuracy()) + " m");
    	
    	drawCurrentPositionOverlay();
    }
    
   

	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}


	@Override
	public void onLocationChanged(Location newLocation) {						
		setCurrentLocation(newLocation);				
				
        Location pointLocation = retrievelocationFromPreferences();
        float distance = newLocation.distanceTo(pointLocation);
        if(distance < POINT_RADIUS)
        {
        	notificacion(distance);        	
        }
	}	
	
	@Override
	protected void onResume() {
		super.onResume();
		getLastLocation();
	}

	@Override
	protected void onPause() {
		super.onPause();
		locationManager.removeUpdates(this);
	}

	@Override
	public void onProviderDisabled(String arg0) {
		// TODO Auto-generated method stub
		
		Toast.makeText(this, "Provider Disabled", Toast.LENGTH_SHORT).show();
		
	}


	@Override
	public void onProviderEnabled(String arg0) {
		// TODO Auto-generated method stub
		Toast.makeText(this, "Provider Enabled", Toast.LENGTH_SHORT).show();
		
	}


	@Override
	public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
		// TODO Auto-generated method stub
		Toast.makeText(this, "Staus Changed", Toast.LENGTH_SHORT).show();
		
	}
	
	public void btnGoToMyLocation_Click(View view){
        animateToCurrentLocation();	
	}
	
	public void drawCurrentPositionOverlay(){
	    List<Overlay> overlays = mapView.getOverlays();
	    overlays.remove(currPos);
	    Drawable marker = getResources().getDrawable(R.drawable.ic_maps_indicator_current_position);
	    currPos = new PointOfInterestOverlay(marker,mapView);
	    if(currentPoint!=null){
	        OverlayItem overlayitem = new OverlayItem(currentPoint, "Yo", "Aqui estoy!");
	        currPos.addOverlay(overlayitem);
	        overlays.add(currPos);
	        currPos.setCurrentLocation(currentLocation);
	        mapView.postInvalidate();
	    }
	}
	
	public void drawPointsOfInterestOverlay(){
	    Drawable marker = getResources().getDrawable(R.drawable.ic_maps_indicator_item_position);
	    PointOfInterestOverlay restaurantPos = new PointOfInterestOverlay(marker,mapView);
	    
        //Load Some Random Coordinates
        RestaurantDataSource restaurantDataSource = new RestaurantDataSource(this);
        restaurantDataSource.open();
        
        List<Restaurant> restaurantList = restaurantDataSource.getAll();               
        List<Overlay> overlays = mapView.getOverlays();        
        
        OverlayItem overlayItemTemp;
        GeoPoint geoPointTemp;
        
        for(Restaurant rest : restaurantList)
        {
        	geoPointTemp = new GeoPoint((int)( Double.parseDouble(rest.getLatitude()) * 1E6), (int) (Double.parseDouble(rest.getLongitude()) * 1E6));
        	overlayItemTemp = new OverlayItem(geoPointTemp, rest.getName(), rest.getAddress() + ", " + rest.getDescription());
        	restaurantPos.addOverlay(overlayItemTemp);
        	if(rest.getName().equals("Archie's pizza"))
        	{
        		saveProximityAlertPoint(geoPointTemp);
        		restaurantAlertName = rest.getName();
        	}
        }
        restaurantDataSource.close();
	    overlays.add(restaurantPos);
	    restaurantPos.setCurrentLocation(currentLocation);
	}	
	
	public void btnShowRestaurantList_Click(View v)
	{		
		boolean calledFromMain = getIntent().getBooleanExtra("calledFromMainActivity", false);
		if(calledFromMain)
			this.finish();
		else			
		{
			Intent i = new Intent(this, TabLayoutActivity.class);
			this.startActivity(i);
			this.finish();
		}
	}
	
	//Proximity alert
	private void saveProximityAlertPoint(GeoPoint geoPoint) {                
        saveCoordinatesInPreferences((float)(geoPoint.getLatitudeE6() / 1E6),
               (float)(geoPoint.getLongitudeE6() / 1E6));
        addProximityAlert((geoPoint.getLatitudeE6() / 1E6), (geoPoint.getLongitudeE6()));
        
    }

    private void addProximityAlert(double latitude, double longitude) {
    	Log.i("App", "Proximity Alert, Lat: " + latitude + "Lon: " + longitude);
    	
        Intent intent = new Intent(PROX_ALERT_INTENT);
        PendingIntent proximityIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
        
        locationManager.addProximityAlert(
            latitude, // the latitude of the central point of the alert region
            longitude, // the longitude of the central point of the alert region
            POINT_RADIUS, // the radius of the central point of the alert region, in meters
            PROX_ALERT_EXPIRATION, // time for this proximity alert, in milliseconds, or -1 to indicate no expiration 
            proximityIntent // will be used to generate an Intent to fire when entry to or exit from the alert region is detected
       );
        
       IntentFilter filter = new IntentFilter(PROX_ALERT_INTENT);         
       Intent temp = registerReceiver(new ProximityIntentReceiver(), filter);
       if(temp == null)
    	   Log.i("App", "intent null");
       else
    	   Log.i("App", "intent not null");
    }    
    
    private void saveCoordinatesInPreferences(float latitude, float longitude) {
        SharedPreferences prefs = 
           this.getSharedPreferences(getClass().getSimpleName(),
                           Context.MODE_PRIVATE);
        SharedPreferences.Editor prefsEditor = prefs.edit();
        prefsEditor.putFloat(POINT_LATITUDE_KEY, latitude);
        prefsEditor.putFloat(POINT_LONGITUDE_KEY, longitude);
        prefsEditor.commit();
    }
    
    private Location retrievelocationFromPreferences() {
        SharedPreferences prefs = 
           this.getSharedPreferences(getClass().getSimpleName(),
                           Context.MODE_PRIVATE);
        Location location = new Location("POINT_LOCATION");
        location.setLatitude(prefs.getFloat(POINT_LATITUDE_KEY, 0));
        location.setLongitude(prefs.getFloat(POINT_LONGITUDE_KEY, 0));
        Log.i("App", "Prefs, Lat: " + location.getLatitude() + " Lon: " + location.getLongitude());
        return location;
    }
    
//    public class MyLocationListener implements LocationListener {
//        public void onLocationChanged(Location location) {
//            Location pointLocation = retrievelocationFromPreferences();
//            float distance = location.distanceTo(pointLocation);
////            if(distance < POINT_RADIUS)
////            {
////            	notificacion(distance);
////            	
////            }
//            Toast.makeText(ShowPointOfInterestMapActivity.this, 
//                    "Distance from Point:"+distance, Toast.LENGTH_LONG).show();
//        }
//        public void onStatusChanged(String s, int i, Bundle b) {            
//        }
//        public void onProviderDisabled(String s) {
//        }
//        public void onProviderEnabled(String s) {            
//        }
//    }
//    
    public void notificacion(float distance )
    {
    	NotificationCompat.Builder mBuilder =
		        new NotificationCompat.Builder(this)
		        .setSmallIcon(R.drawable.ic_launcher)
		        .setContentTitle("Hambre?")
		        .setContentText("Ven a " + restaurantAlertName + ", a " + ((int) distance) + " m");
		// Creates an explicit intent for an Activity in your app
		Intent resultIntent = new Intent(this, ShowPointOfInterestMapActivity.class);

		// The stack builder object will contain an artificial back stack for the
		// started Activity.
		// This ensures that navigating backward from the Activity leads out of
		// your application to the Home screen.
		TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
		// Adds the back stack for the Intent (but not the Intent itself)
		stackBuilder.addParentStack(LoginActivity.class);
		// Adds the Intent that starts the Activity to the top of the stack
		stackBuilder.addNextIntent(resultIntent);
		PendingIntent resultPendingIntent =
		        stackBuilder.getPendingIntent(
		            0,
		            PendingIntent.FLAG_UPDATE_CURRENT
		        );
		mBuilder.setContentIntent(resultPendingIntent);
		NotificationManager mNotificationManager =
		    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		// mId allows you to update the notification later on.
		mNotificationManager.notify(1, mBuilder.build());
    }
}
